home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 January / macformat-033.iso / mac / Shareware City / Developers / VideoToolbox / VideoToolboxSources / AtExitToShell.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-27  |  4.2 KB  |  111 lines  |  [TEXT/CWIE]

  1. /*
  2. AtExitToShell.c
  3.  
  4.     void YourFunction(void);
  5.  
  6.     error=AtExitToShell(YourFunction);
  7.  
  8. AtExitToShell(YourFunction) requests that your function be called when the
  9. application quits, i.e. calls the ExitToShell trap, which tells the MacOS that
  10. it's done. Your function must have no arguments and no return value.
  11.  
  12. Many VideoToolbox routines set up interrupt service routines that must be killed
  13. before the program goes away. We want to kill these whether we quit via exit(),
  14. abort(), or the ExitToShell trap is invoked directly, e.g. if user types "ES"
  15. in MacsBug. The only way to be sure of killing something before the application
  16. goes away is to attach its killer, by patching, to the ExitToShell trap. That's
  17. what's done here.
  18.  
  19. AtExitToShell() is closely modeled on the ANSI function atexit(). I wrote it to
  20. overcome the restrictive implementation of atexit() and _atexit() in CodeWarrior:
  21. they only invoke your functions if the ANSI function exit() is called, NOT if
  22. you call abort(), or the user types "ES" in MacsBug. I think that AtExitToShell
  23. is equivalent to the non-ANSI _atexit() routine provided by the Symantec THINK C
  24. environment.
  25.  
  26. The registration list (of user functions) is last-in, first-out. When you
  27. eventually quit, your functions will be called in reverse of the order in which
  28. you registered them. No checking is made for duplication: the same function may
  29. be registed multiple times, and will be called multiple times.
  30.  
  31. CAUTION: your application's runtime environment will normally have shut itself
  32. down by the time it calls ExitToShell(), so a function scheduled for that time
  33. should not assume the availability of such services (e.g. printf). There's no
  34. restriction on the use of MacOS services.
  35.  
  36. CAUTION: the atexit() and _atexit() routines should not be used in MATLAB code
  37. resources. Your function would only be invoked when MATLAB quits, after your code
  38. resources have already been flushed, so you'll crash. Conditionals below make
  39. AtExitToShell() innocuous if MATLAB is true, making this routine do nothing.
  40. However, it ought to be fairly easy to get MATLAB to call MyExitToShell() just
  41. before it disposes of our MEX resource, in which case all the existing calls to
  42. AtExitToShell() would then do the right thing.
  43.  
  44. The code to patch ExitToShell is based on examples that appeared in UseNet
  45. csmp-digest-v3-046 by Kevin Bell (kbell@cs.utexas.edu) and Bill Hofmann
  46. (wdh@netcom.com) in response to a query by Steve Coy (stevec@jolt.mpx.com.au)
  47.  
  48. HISTORY:
  49. 10/27/94 dgp wrote the ExitToShell patch, based on code from UseNet csmp-digest.
  50. 6/17/95 dgp wrote AtExitToShell.c
  51. 7/1/95 dgp made compatible with pre-universal apple headers. 
  52.     Disable if MATLAB is true. Added comments about MATLAB. 
  53. 7/17/95 dgp made compatible with pre-universal headers
  54. */
  55. #include "VideoToolbox.h"
  56. #ifndef __TRAPS__
  57.     #include <Traps.h>        // _ExitToShell
  58. #endif
  59. #include <SegLoad.h>    // ExitToShell()
  60. #if UNIVERSAL_HEADERS
  61.     typedef UniversalProcPtr TrapAddressType;
  62. #else
  63.     #define UniversalProcPtr ProcPtr
  64.     #define NewRoutineDescriptor(a,b,c) a
  65.     typedef long TrapAddressType;
  66. #endif
  67. static pascal void MyExitToShell(void);
  68. #define FUNCTIONS 35
  69. static UniversalProcPtr oldExitToShellTrapAddress=NULL;
  70. static void (*userFunction[FUNCTIONS])(void);
  71.  
  72. int AtExitToShell(void (*userFunctionPtr)(void))
  73. {
  74.     UniversalProcPtr myExitToShellUPP;
  75.     int i;
  76.  
  77.     if(oldExitToShellTrapAddress==NULL){
  78.         #if !MATLAB
  79.             myExitToShellUPP=NewRoutineDescriptor((ProcPtr)MyExitToShell
  80.                 ,kPascalStackBased,GetCurrentISA());
  81.             oldExitToShellTrapAddress=(UniversalProcPtr)GetToolTrapAddress(_ExitToShell);
  82.             SetToolTrapAddress((TrapAddressType)myExitToShellUPP,_ExitToShell);
  83.         #else
  84.             // Someday we should put code here that asks MATLAB to call MyExitToShell
  85.             // just before disposing of our MEX resource.
  86.         #endif
  87.         for(i=0;i<FUNCTIONS;i++)userFunction[i]=NULL;
  88.     }
  89.     for(i=0;i<FUNCTIONS;i++)if(userFunction[i]==NULL){
  90.         userFunction[i]=userFunctionPtr;
  91.         return 0;    // success
  92.     }
  93.     return 1;        // failure
  94. }
  95.  
  96. static pascal void MyExitToShell(void)
  97. {
  98.     int i;
  99.  
  100.     SetCurrentA5();
  101.     #if !MATLAB
  102.         SetToolTrapAddress((TrapAddressType)oldExitToShellTrapAddress,_ExitToShell);
  103.     #endif
  104.     for(i=FUNCTIONS-1;i>=0;i--)if(userFunction[i]!=NULL){
  105.         (*userFunction[i])();
  106.     }
  107.     #if !MATLAB
  108.         ExitToShell();
  109.     #endif
  110. }
  111.